package com.abe.mvp.view.fragment;

import it.moondroid.coverflow.components.ui.containers.FeatureCoverFlow;

import java.util.ArrayList;
import java.util.List;

import lecho.lib.hellocharts.model.ComboLineColumnChartData;
import lecho.lib.hellocharts.view.ComboLineColumnChartView;

import org.xutils.view.annotation.ViewInject;

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.LinearLayout;

import com.abe.config.Constants;
import com.abe.config.PatternConstants;
import com.abe.mvp.model.bean.exercise.ExerciseGroupBean;
import com.abe.mvp.model.bean.exercise.ExerciseNodeBean;
import com.abe.mvp.view.activity.FragmentCallbackListener.CallbackListener;
import com.abe.mvp.view.adapter.PatternCoverFlowAdapter;
import com.abe.mvp.view.fragment.base.BaseExerciseFragment;
import com.abe.threadmill.R;
import com.abe.utils.NormalUtils;
import com.abe.utils.ThreadPoolUtils;
import com.abe.utils.ToastUtils;

public class ExercisePatternFragment extends BaseExerciseFragment implements
		FeatureCoverFlow.OnScrollPositionListener, OnItemClickListener {

	private CallbackListener callback;

	private static final int APP_TOAST = 0x001;
	private static final int TWINKLE_CHART = 0x002;
	private static final int CHART_INIT = 0x003;

	private static final int SHOW_PATTERNS = 0x004;
	private static final int HIDE_PATTERNS = 0x005;
	private static final int SHOW_SELECT = 0x006;

	private static final int SET_SPEED = 0x007;
	private static final int SET_SLOPE = 0x008;

	private LinearLayout coverflow_chart_layout;
	private FeatureCoverFlow coverflow_chart;
	private PatternCoverFlowAdapter adapter;

	@ViewInject(R.id.pattern_chart)
	private ComboLineColumnChartView pattern_chart;
	/** 原始数据 */
	private ComboLineColumnChartData current_data;
	/** 闪烁数据 */
	private ComboLineColumnChartData twinkle_data;
	/** 速度m/s */
	private List<Float> speeds_ms;
	/** 速度km/h */
	private List<Float> speeds;
	private List<Float> slopes;
	/** 记录手动设置速度数组 */
	private List<Float> change_speeds;
	private List<Float> change_slopes;
	private List<List<ExerciseNodeBean>> nodeList;
	/** 当前速度km/h */
	private Float current_speed_kmh;
	/** 当前闪烁位置 （速度，坡度） */
	private int current_twinkle_pos = 0;
	/** 启动状态 */
	private boolean is_run = false;
	/** 每组持续时间s */
	private int keep_group_time = 30;
	
	private boolean isGroupChange=false;

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		callback = (CallbackListener) getActivity();
		View view = this
				.onCreateView(inflater, R.layout.activity_tm_tab_pattern,
						container, savedInstanceState);
		initView();
		initCoverFlowAndPattern(view);
		callback.fragmentReady();
		return view;
	}

	public void initView() {
		/** 禁止手势缩放 */
		pattern_chart.setZoomEnabled(false);
		/** 是否运行标记 */
		is_run = false;
		/***/
		allow_change_in_running = true;
	}

	private void initCoverFlowAndPattern(View view) {
		/** 画廊 */
		adapter = new PatternCoverFlowAdapter(getActivity());
		adapter.setData(PatternConstants.getPatternBeans());
		coverflow_chart_layout = (LinearLayout) view
				.findViewById(R.id.coverflow_chart_layout);
		coverflow_chart_layout.setBackgroundColor(getActivity().getResources()
				.getColor(R.color.transparent));
		coverflow_chart = (FeatureCoverFlow) view
				.findViewById(R.id.coverflow_chart);
		coverflow_chart.setAdapter(adapter);
		coverflow_chart.setOnItemClickListener(this);
		coverflow_chart.setOnScrollPositionListener(this);
	}

	@Override
	public void startExercise() {
		is_run = true;
		ThreadPoolUtils.execute(new TwinkleChartThread());
		callback.startBack();
	}

	@Override
	public void stopExercise() {
		if (is_run) {
			is_run = false;
		}
	}

	@Override
	public void selectPosition(int pos) {
		int size = PatternConstants.getPatternBeans().size();
		pos = (pos >= size) ? size - 1 : pos;
		/** 初始化原始速度 */
		speeds = PatternConstants
				.getListByArray(PatternConstants.model_speeds[pos]);
		speeds_ms = PatternConstants.getListByArray(PatternConstants
				.SpeedConvertByKMHArray(PatternConstants.model_speeds[pos]));
		slopes = PatternConstants
				.getListByArray(PatternConstants.model_slopes[pos]);
		/** 初始化速度记录数组 */
		change_speeds = speeds;
		change_slopes = slopes;
		current_data = PatternConstants.getComboLineColumnChartData(
				change_speeds, change_slopes);
		pattern_chart.setComboLineColumnChartData(current_data);
		/** 记录节点（速度设置，坡度设置） */
		nodeList = new ArrayList<List<ExerciseNodeBean>>();
		for (int i = 0; i < speeds.size(); i++) {
			List<ExerciseNodeBean> node = new ArrayList<ExerciseNodeBean>();
			nodeList.add(node);
		}
		current_twinkle_pos = 0;
	}

	/**
	 * @param status
	 *            false:隐藏，true：显示
	 * */
	public void setItemTwinkle(boolean status) {
		/** 控制数据与时间来实现闪烁状态 */
		List<Float> temSpeeds = new ArrayList<Float>();
		temSpeeds.addAll(change_speeds);
		if (status) {
			temSpeeds.set(current_twinkle_pos,
					change_speeds.get(current_twinkle_pos));
		} else {
			temSpeeds.set(current_twinkle_pos, 0f);
		}
		twinkle_data = PatternConstants.getComboLineColumnChartData(temSpeeds,
				change_slopes);
	}

	/** 延时发送速度坡度 */
	class DelaySendSpeedSlope implements Runnable {
		@Override
		public void run() {
			isGroupChange=true;
			/** 通知设置跑步机速度 */
			localSendMessage(NormalUtils.getMessage(SET_SPEED,
					current_speed_kmh));
			try {
				Thread.sleep(150);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			/** 通知设置跑步机坡度 */
			localSendMessage(NormalUtils.getMessage(SET_SLOPE, current_slope));
			try {
				Thread.sleep(150);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			isGroupChange=false;
		}

	}

	/**
	 * 闪烁线程
	 * */
	class TwinkleChartThread implements Runnable {
		@Override
		public void run() {
			ExerciseGroupBean groupBean = new ExerciseGroupBean();
			/** 记录当前组的的运行时间 */
			int run = 0;
			while (is_run && current_twinkle_pos < speeds.size()) {
				List<ExerciseNodeBean> current_posList = nodeList
						.get(current_twinkle_pos);
				/** 当前组速度坡度 */
				current_slope = slopes.get(current_twinkle_pos);
				current_speed = speeds_ms.get(current_twinkle_pos);
				current_speed_kmh = speeds.get(current_twinkle_pos);
				old_slope = current_slope;
				old_speed = current_speed;
				ThreadPoolUtils.execute(new DelaySendSpeedSlope());
				/** 根据持续时间保持闪烁 */
				run = 0;
				for (int i = 0; i < keep_group_time / 0.5 && is_run; i++) {
					try {
						/** 每隔500ms切换一下视图数据 */
						setItemTwinkle(i % 2 == 0);
						new MyHandler(Looper.getMainLooper())
								.sendEmptyMessage(TWINKLE_CHART);
						if (is_run) {
							Thread.sleep(500);
							run++;
							if (run % 2 == 0) {
								/** 判断速度是否改变，改变记录时间节点 */
								if (current_speed != old_speed
										|| current_slope != old_slope) {
									current_posList.add(new ExerciseNodeBean(
											run / 2, old_speed, old_slope));
									old_speed = current_speed;
									old_slope = current_slope;
								}
								groupBean = getCumulativeData(run);
								callback.updateExercise(groupBean);
							}
						}
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				nodeList.set(current_twinkle_pos, current_posList);
				/** 设置闪烁位置 */
				current_twinkle_pos++;
			}
			/** 结束 */
			callback.stopBack(is_run, groupBean);
		}
	}

	private ExerciseGroupBean getCumulativeData(int current) {
		ExerciseGroupBean groupBean = new ExerciseGroupBean();
		groupBean.setMaxNum(0);
		/** 累计锻炼时间s */
		int keepTime = (int) (current_twinkle_pos * keep_group_time + current * 0.5);
		/** 累计锻炼距离 */
		float distance = 0;
		/** 累计坡度 */
		float allslopes = 0;
		/** 第1组至第current_twinkle_pos组（已完成组） */
		for (int i = 0; i < current_twinkle_pos; i++) {
			/** i组累计锻炼距离 */
			float current_distance = 0;
			/** i组累计坡度 */
			float current_allslopes = 0;
			/** i组的速度坡度改变节点 */
			List<ExerciseNodeBean> nodeBeans = nodeList.get(i);
			/** 当前组无改变节点 */
			if (nodeBeans.size() == 0) {
				current_distance = (float) (keep_group_time * speeds_ms
						.get(current_twinkle_pos));
				current_allslopes = (float) (keep_group_time * slopes
						.get(current_twinkle_pos));
			} else {
				/** 节点1： 第一段 ：按照模式速度，坡度 */
				ExerciseNodeBean eBean_0 = nodeBeans.get(0);
				current_distance = eBean_0.getNodeTime()
						* speeds_ms.get(current_twinkle_pos);
				current_allslopes = eBean_0.getNodeTime()
						* slopes.get(current_twinkle_pos);
				/** 中间按照设置速度 */
				for (int j = 1; j < nodeBeans.size(); j++) {
					ExerciseNodeBean eBean_previous = nodeBeans.get(j - 1);
					ExerciseNodeBean eBean = nodeBeans.get(j);
					current_distance = current_distance
							+ (eBean.getNodeTime() - eBean_previous
									.getNodeTime())
							* eBean_previous.getNodeSpeed();
					current_allslopes = current_allslopes
							+ (eBean.getNodeTime() - eBean_previous
									.getNodeTime())
							* eBean_previous.getNodeSlope();
				}
				/** 最后一段 */
				ExerciseNodeBean eBean_last = nodeBeans
						.get(nodeBeans.size() - 1);
				current_distance = (float) (current_distance + (keep_group_time - eBean_last
						.getNodeTime()) * eBean_last.getNodeSpeed());
				current_allslopes = (float) (current_allslopes + (keep_group_time - eBean_last
						.getNodeTime()) * eBean_last.getNodeSlope());
			}
			/** 将i组数据计算入累加 */
			distance = distance + current_distance;
			allslopes = allslopes + current_allslopes;
		}
		/** 当前组组累计锻炼距离 */
		float current_distance = 0;
		/** 当前组组累计坡度 */
		float current_allslopes = 0;
		/** 当前组组的速度坡度改变节点 */
		List<ExerciseNodeBean> nodeBeans = nodeList.get(current_twinkle_pos);
		/** 当前组无改变节点 */
		if (nodeBeans.size() == 0) {
			current_distance = (float) (current * 0.5 * speeds_ms
					.get(current_twinkle_pos));
			current_allslopes = (float) (current * 0.5 * slopes
					.get(current_twinkle_pos));
		} else {
			/** 节点1： 第一段 ：按照模式速度，坡度 */
			ExerciseNodeBean eBean_0 = nodeBeans.get(0);
			current_distance = eBean_0.getNodeTime()
					* speeds_ms.get(current_twinkle_pos);
			current_allslopes = eBean_0.getNodeTime()
					* slopes.get(current_twinkle_pos);
			/** 中间按照设置速度 */
			for (int j = 1; j < nodeBeans.size(); j++) {
				ExerciseNodeBean eBean_previous = nodeBeans.get(j - 1);
				ExerciseNodeBean eBean = nodeBeans.get(j);
				current_distance = current_distance
						+ (eBean.getNodeTime() - eBean_previous.getNodeTime())
						* eBean_previous.getNodeSpeed();
				current_allslopes = current_allslopes
						+ (eBean.getNodeTime() - eBean_previous.getNodeTime())
						* eBean_previous.getNodeSlope();
			}
			/** 当前段 */
			ExerciseNodeBean eBean_last = nodeBeans.get(nodeBeans.size() - 1);

			current_distance = (float) (current_distance + (current * 0.5 - eBean_last
					.getNodeTime()) * eBean_last.getNodeSpeed());
			current_allslopes = (float) (current_allslopes + (current * 0.5 - eBean_last
					.getNodeTime()) * eBean_last.getNodeSlope());

		}
		/** 累加 */
		distance = distance + current_distance;
		allslopes = allslopes + current_allslopes;
		float calorie = Constants.getKcal(distance);
		groupBean.setDistance(distance);
		groupBean.setKeepTime(keepTime);
		groupBean.setCalorie(calorie);
		groupBean.setAverageSlope(allslopes / keepTime);
		groupBean.setAverageSpeed(distance / keepTime);
		return groupBean;
	}

	@Override
	public void onStop() {
		super.onStop();
		is_run = false;
	}

	/** Handler快捷 */
	protected void localSendMessage(Message message) {
		new MyHandler(Looper.getMainLooper()).sendMessage(message);
	}

	/** Handler快捷 */
	protected void localSendEmptyMessage(int What) {
		new MyHandler(Looper.getMainLooper()).sendEmptyMessage(What);
	}

	class MyHandler extends Handler {
		public MyHandler(Looper looper) {
			super(looper);
		}

		public void handleMessage(Message msg) {
			switch (msg.what) {
			case SET_SPEED:
				callback.setSpeed(Float.parseFloat(msg.obj.toString()));
				break;
			case SET_SLOPE:
				callback.setSlope(Float.parseFloat(msg.obj.toString()));
				break;
			case APP_TOAST:
				ToastUtils.showShort(getContext(), msg.obj.toString());
				break;
			case TWINKLE_CHART: {
				/** 当前闪烁位置:current_twinkle_pos */
				pattern_chart.setComboLineColumnChartData(twinkle_data);
				pattern_chart.setVisibility(View.VISIBLE);
			}
				break;
			case CHART_INIT: {
				pattern_chart.setComboLineColumnChartData(current_data);
			}
				break;
			case SHOW_PATTERNS: {
				coverflow_chart_layout.setVisibility(View.VISIBLE);
			}
				break;
			case HIDE_PATTERNS: {
				coverflow_chart_layout.setVisibility(View.GONE);
			}
				break;
			case SHOW_SELECT: {
				pattern_chart.setVisibility(View.VISIBLE);
			}
				break;
			default:
				break;
			}
		}

	}

	@Override
	public void onScrolledToPosition(int position) {

	}

	@Override
	public void onScrolling() {

	}

	@Override
	public void onItemClick(AdapterView<?> parent, View view, int pos, long id) {
		if (parent.equals(coverflow_chart)) {
			/** 选中模式 */
			selectPosition(pos);
			localSendEmptyMessage(HIDE_PATTERNS);
			localSendEmptyMessage(SHOW_SELECT);
			isCanStart = true;
		}
	}

	@Override
	public void setSlope(float slope) {
		if (allow_change_in_running) {
			current_slope = slope;
			change_slopes.set(current_twinkle_pos, current_slope);
			current_data = PatternConstants.getComboLineColumnChartData(
					change_speeds, change_slopes);
		}
	}

	@Override
	public void setSpeed(float speed) {
		if (allow_change_in_running) {
			current_speed = Constants.SpeedConvertByKMH(speed);
			current_speed_kmh = speed;
			change_speeds.set(current_twinkle_pos, current_speed_kmh);
			current_data = PatternConstants.getComboLineColumnChartData(
					change_speeds, change_slopes);
		}
	}

	@Override
	public boolean checkInitComplete() {
		return isCanStart;
	}

	@Override
	public boolean checkIsCanSetSpeedSlope() {
		return !isGroupChange;
	}
}
